package com.runvp.common.pay.wechat;

import com.runvp.common.exception.base.BaseException;
import org.springframework.util.Base64Utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.Signature;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class V3Sign {


    /**
     * 构造验签名串.
     *
     * @param wechatpayTimestamp HTTP头 Wechatpay-Timestamp 中的应答时间戳。
     * @param wechatpayNonce     HTTP头 Wechatpay-Nonce 中的应答随机串
     * @param body               响应体
     * @return the string
     */
    public static String responseSign(String wechatpayTimestamp, String wechatpayNonce, String body) {
        return Stream.of(wechatpayTimestamp, wechatpayNonce, body)
                .collect(Collectors.joining("\n", "", "\n"));
    }
    public static String buildSignStr(Map<String,Object> param) {
        StringBuilder sb = new StringBuilder();
        for(Object obj: param.values()){
            sb.append(obj).append("\n");
        }
        return sb.toString();
    }
    /**
     * sha256_HMAC加密
     *
     * @param parameters 参数
     * @param key        秘钥
     * @return 加密后字符串
     */
    public static String sha256_HMAC(String parameters, String key) {
        // 对数据进行排序
        // 待签名字符串
        String message = parameters;

        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes).toUpperCase();
        } catch (Exception e) {
            System.out.println("Error HmacSHA256 ===========" + e.getMessage());
        }
        return hash;
    }
    /**
     * 将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }
    /**
     * V3  SHA256withRSA 签名.
     *
     * @param method       请求方法  GET  POST PUT DELETE 等
     * @param canonicalUrl 例如  https://api.mch.weixin.qq.com/v3/pay/transactions/app?version=1 ——> /v3/pay/transactions/app?version=1
     * @param timestamp    当前时间戳   因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致
     * @param nonceStr     随机字符串  要和TOKEN中的保持一致
     * @param body         请求体 GET 为 "" POST 为JSON
     * @param keyPair      商户API 证书解析的密钥对  实际使用的是其中的私钥
     * @return the string
     */
    public static String sign(String method, String canonicalUrl, long timestamp, String nonceStr, String body, KeyPair keyPair)  {
        try{
            String signatureStr = Stream.of(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body)
                    .collect(Collectors.joining("", "", ""));
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(keyPair.getPrivate());
            sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
            return Base64Utils.encodeToString(sign.sign());
        }catch (Exception e){
            throw new BaseException("签名失败");
        }

    }
}
